using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xna.Framework.Graphics;
using RSCore;
using Terraria.GameContent;
using Terraria.GameInput;

namespace _ReplaceString_.UI.Styles;
public record UIScroll() : UIStyle(false, true)
{
	public static UIScroll Vertical => new VerticalScroll();
	public static UIScroll Horizontal => new HorizontalScroll();
	public static UIScroll Window { get; } = new ScrollWindow();
}

/// <summary>
/// 上下滚动
/// </summary>
file record VerticalScroll : UIScroll
{
	private float opacity = 0;
	public override void Apply(UIBase ui)
	{
		ui.MaxHeight = new StyleDimension(float.MaxValue, 0);
	}

	public override void Update(UIBase ui)
	{
		opacity = opacity.Approach(0, -0.05f);
		if (!ui.IsMouseHovering)
		{
			return;
		}
		var parent = ui.Parent;
		var windowHeight = parent._innerDimensions.Height;
		var height = ui._outerDimensions.Height;
		if (windowHeight > height)
		{
			return;
		}
		Debug.Assert(parent.OverflowHidden, "Parent should have style UIScroll.Window");
		if (PlayerInput.ScrollWheelDeltaForUI != 0)
		{
			ui.Top.Pixels += PlayerInput.ScrollWheelDeltaForUI / 3f;
			ui.Top.Pixels = Math.Clamp(ui.Top.Pixels, windowHeight - height, 0);
			opacity = opacity.Approach(5, 0.5f);
		}
		ui.Parent.Recalculate();
	}

	public override void Draw(UIBase ui)
	{
		float windowHeight = ui.Parent._innerDimensions.Height;
		float height = ui._outerDimensions.Height;
		if (windowHeight > height)
		{
			return;
		}

		float length = windowHeight * (windowHeight / height);
		float minTop = windowHeight - height;
		float start = (windowHeight - length) * (ui.Top.Pixels / minTop);
		const int barWidth = 6;
		Main.spriteBatch.Draw(
			TextureAssets.MagicPixel.Value,
			new Rectangle(
				(int)(ui._dimensions.X + ui._dimensions.Width - barWidth),
				(int)(ui.Parent._innerDimensions.Y + start),
				barWidth,
				(int)length),
			ui.ExtraColor * Math.Min(opacity, 1));
	}
}

/// <summary>
/// 左右滚动
/// </summary>
file record HorizontalScroll : UIScroll
{
	private float opacity = 0;
	public override void Apply(UIBase ui)
	{
		ui.MaxWidth = new StyleDimension(float.MaxValue, 0);
	}

	public override void Update(UIBase ui)
	{
		opacity = opacity.Approach(0, -0.05f);
		if (!ui.IsMouseHovering)
		{
			return;
		}
		Debug.Assert(ui.Parent != null);
		var parent = ui.Parent;
		var windowWidth = parent._innerDimensions.Width;
		var width = ui._outerDimensions.Width;
		if (windowWidth > width)
		{
			return;
		}
		Debug.Assert(parent.OverflowHidden, "Parent should have style UIScroll.Window");
		if (PlayerInput.ScrollWheelDeltaForUI != 0)
		{
			ui.Left.Pixels += PlayerInput.ScrollWheelDeltaForUI / 3f;
			ui.Left.Pixels = Math.Clamp(ui.Left.Pixels, windowWidth - width, 0);
			opacity = opacity.Approach(5, 0.5f);
		}
		ui.Parent.Recalculate();
	}

	public override void Draw(UIBase ui)
	{
		float windowWidth = ui.Parent._innerDimensions.Width;
		float width = ui._outerDimensions.Width;
		if (windowWidth > width)
		{
			return;
		}

		float length = windowWidth * (windowWidth / width);
		float minLeft = windowWidth - width;
		float start = (windowWidth - length) * (ui.Left.Pixels / minLeft);
		const int barWidth = 6;
		Main.spriteBatch.Draw(
			TextureAssets.MagicPixel.Value,
			new Rectangle(
				(int)(ui.Parent._innerDimensions.X + start),
				(int)(ui._dimensions.Y + ui._dimensions.Width - barWidth),
				(int)length,
				barWidth),
			ui.ExtraColor * Math.Min(opacity, 1));
	}
}

file record ScrollWindow : UIScroll
{
	public override void Apply(UIBase ui)
	{
		ui.OverflowHidden = true;
		ui.OnRecalculate += OnRecalculate;
	}

	/// <summary>
	/// 修正UI缩放带来的误差
	/// </summary>
	/// <param name="obj"></param>
	/// <returns></returns>
	private bool OnRecalculate(UIBase obj)
	{
		var dim = obj._innerDimensions;
		var pos = new Vector2(dim.X, dim.Y);
		var scaledPos = Vector2.Transform(pos, Main.UIScaleMatrix);
		if((int)scaledPos.X < Math.Round(scaledPos.X))
		{
			obj._innerDimensions.X += 0.501f / Main.UIScale;
		}
		if((int)scaledPos.Y < Math.Round(scaledPos.Y))
		{
			obj._innerDimensions.Y += 0.501f / Main.UIScale;
		}
		return false;
	}
}
